/*
* This file is part of RoboDS (http://code.google.com/p/robods/)
* Copyright (C) 2007 Blakharaz
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* 
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
* 
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
*/

#include "SpriteManager.h"

#include <PA9.h>
#include "gfx/all_gfx.c"
#include "gfx/all_gfx.h"

#include "DsSprite.h"
#include "Logger.h"

namespace robo
{

    SpriteManager* SpriteManager::msSingleton = NULL;

    SpriteManager::SpriteManager()
    {
        PA_InitAllSpriteDraw();  // Inits the sprite draw mode, necessary for the pixel-perfect touch detection

        for (unsigned short i=0; i<127; ++i)
        {
            mSpritePool.insert(i);
        }

        initializeLowerScreen();
        initializeUpperScreen();

        Logger::getSingleton()->log("Initialized!");

        msSingleton = this;
    }

    void SpriteManager::initializeUpperScreen()
    {
	    PA_LoadSpritePal(1, // Screen
			    SpriteManager::PALETTE_FACTORY_TILES, // Palette number
			    (void*)factory_tiles_Pal);	// Palette name
	    PA_LoadSpritePal(1, // Screen
			    SpriteManager::PALETTE_BOTS, // Palette number
			    (void*)bots_Pal);	// Palette name

        PA_LoadPAGfxRotBg(1, SpriteManager::BACKGROUND_MAP, factory_tiles, 0);

    }

    void SpriteManager::initializeLowerScreen()
    {
	    PA_LoadSpritePal(0, // Screen
		    SpriteManager::PALETTE_UI, // Palette number
		    (void*)ui_background_Pal);	// Palette name

        PA_LoadPAGfxLargeBg(0, 0, ui_background); 

	    PA_LoadSpritePal(0, // Screen
		    SpriteManager::PALETTE_CARDS, // Palette number
		    (void*)cards_Pal);	// Palette name

        PA_LoadSpritePal(0, // Screen
		    SpriteManager::PALETTE_BUTTONS, // Palette number
		    (void*)buttons_Pal);	// Palette name
    }

    SpriteManager* SpriteManager::getSingleton()
    {
        if (msSingleton == NULL)
        {
            msSingleton = new SpriteManager();
        }
        return msSingleton;
    }

    int SpriteManager::createSprite(DsSprite* sprite, int screen)
    {
        unsigned short spriteidx = *mSpritePool.begin();
        ///@todo use sprite index pool

        switch (sprite->getSpriteType())
        {
        case DsSprite::SPRITE_CARD_MOVEMENT_1:
            PA_CreateSprite(screen, spriteidx,(void*)movement_1_Sprite, OBJ_SIZE_32X64, 1, SpriteManager::PALETTE_CARDS, 0, 0);
            break;
        case DsSprite::SPRITE_CARD_MOVEMENT_2:
            PA_CreateSprite(screen, spriteidx,(void*)movement_2_Sprite, OBJ_SIZE_32X64, 1, SpriteManager::PALETTE_CARDS, 0, 0);
            break;
        case DsSprite::SPRITE_CARD_MOVEMENT_3:
            PA_CreateSprite(screen, spriteidx,(void*)movement_3_Sprite, OBJ_SIZE_32X64, 1, SpriteManager::PALETTE_CARDS, 0, 0);
            break;
        case DsSprite::SPRITE_CARD_MOVEMENT_BACK:
            PA_CreateSprite(screen, spriteidx,(void*)movement_back_Sprite, OBJ_SIZE_32X64, 1, SpriteManager::PALETTE_CARDS, 0, 0);
            break;
        case DsSprite::SPRITE_CARD_TURN_AROUND:
            PA_CreateSprite(screen, spriteidx,(void*)turn_around_Sprite, OBJ_SIZE_32X64, 1, SpriteManager::PALETTE_CARDS, 0, 0);
            break;
        case DsSprite::SPRITE_CARD_TURN_LEFT:
            PA_CreateSprite(screen, spriteidx,(void*)turn_left_Sprite, OBJ_SIZE_32X64, 1, SpriteManager::PALETTE_CARDS, 0, 0);
            break;
        case DsSprite::SPRITE_CARD_TURN_RIGHT:
            PA_CreateSprite(screen, spriteidx,(void*)turn_right_Sprite, OBJ_SIZE_32X64, 1, SpriteManager::PALETTE_CARDS, 0, 0);
            break;
        case DsSprite::SPRITE_POWER_BUTTON:
            PA_CreateSprite(screen, spriteidx,(void*)power_button_Sprite, OBJ_SIZE_32X32, 1, SpriteManager::PALETTE_BUTTONS, 0, 0);
            break;
        case DsSprite::SPRITE_OK_BUTTON:
            PA_CreateSprite(screen, spriteidx,(void*)ok_button_Sprite, OBJ_SIZE_64X64, 1, SpriteManager::PALETTE_BUTTONS, 0, 0);
            break;
        case DsSprite::SPRITE_BOT_1:
            PA_CreateSprite(screen, spriteidx,(void*)kittybot_Sprite, OBJ_SIZE_16X16, 1, SpriteManager::PALETTE_BOTS, 0, 0);
		    PA_SetSpritePrio(screen, spriteidx, SpriteManager::BACKGROUND_ROBOT_SPRITES);
            break;
        case DsSprite::SPRITE_BOT_2:
            PA_CreateSprite(screen, spriteidx,(void*)bunnybot_Sprite, OBJ_SIZE_16X16, 1, SpriteManager::PALETTE_BOTS, 0, 0);
		    PA_SetSpritePrio(screen, spriteidx, SpriteManager::BACKGROUND_ROBOT_SPRITES);
            break;
            
        }
     
        mDisplayedSprites[spriteidx] = sprite;
	    mSpritePool.erase(mSpritePool.begin());
      	
        return spriteidx;
    }

    DsSprite* SpriteManager::getTouchedSprite() const
    {
        for (std::map<unsigned short, DsSprite*>::const_iterator 
            it = mDisplayedSprites.begin();
            it != mDisplayedSprites.end(); ++it)
        {
            if (PA_SpriteTouched(it->first))
            {
                return it->second;
            }
        }

        return NULL;
    }

    void SpriteManager::releaseSprite(unsigned short spriteno)
    {
	    std::map<unsigned short, DsSprite*>::iterator it
		    = mDisplayedSprites.find(spriteno);
	    mSpritePool.insert(spriteno);
    }

    DsSprite::SpriteType SpriteManager::getCardSprite(Card::CardType card) const
    {
        switch (card)
        {
        case Card::CARD_MOVEMENT_1:
            return DsSprite::SPRITE_CARD_MOVEMENT_1;
        case Card::CARD_MOVEMENT_2:
            return DsSprite::SPRITE_CARD_MOVEMENT_2;
        case Card::CARD_MOVEMENT_3:
            return DsSprite::SPRITE_CARD_MOVEMENT_3;
        case Card::CARD_MOVEMENT_BACK:
            return DsSprite::SPRITE_CARD_MOVEMENT_BACK;
        case Card::CARD_TURN_AROUND:
            return DsSprite::SPRITE_CARD_TURN_AROUND;
        case Card::CARD_TURN_LEFT:
            return DsSprite::SPRITE_CARD_TURN_LEFT;
        case Card::CARD_TURN_RIGHT:
            return DsSprite::SPRITE_CARD_TURN_RIGHT;
        }

        return DsSprite::SPRITE_CARD_TURN_RIGHT;
    }


}
